package com.duolebo.uteped_sdk.msg;

import android.app.LocaleManager;
import android.os.Build;
import android.os.Handler;
import android.os.LocaleList;
import android.text.format.DateFormat;

import androidx.annotation.ChecksSdkIntAtLeast;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.os.LocaleListCompat;

import com.duolebo.uteped_sdk.UTEPedEventHandler;
import com.duolebo.uteped_sdk.remind.MusicRemind;
import com.duolebo.uteped_sdk.utils.BluetoothHelper;
import com.duolebo.uteped_sdk.utils.Const;
import com.duolebo.uteped_sdk.utils.DataSyncHelper;
import com.duolebo.uteped_sdk.utils.DeviceHelper;
import com.duolebo.uteped_sdk.utils.Logger;
import com.duolebo.uteped_sdk.utils.SPHelper;
import com.duolebo.uteped_sdk.utils.Tools;
import com.yc.nadalsdk.bean.Response;
import com.yc.nadalsdk.ble.open.UteBleConnection;
import com.yc.nadalsdk.log.LogUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;

/**
 * @Author: LiuYang
 * @Date: 2023/12/11 20:16
 * @Description:
 */
public class CommonMessage extends BaseMessage {
    private final static String PATH = "common";
    // 是否开启日志
    private final static String M_setLogEnable = "setLogEnable";
    // 检查通知权限
    private final static String M_checkNotificationEnable = "checkNotificationEnable";
    private final static String M_isNotificationEnable = "isNotificationEnable";
    private final static String M_toNotificationPage = "toNotificationPage";
    // 同步手表数据
    private final static String M_syncData = "syncData";
    private final static String M_removeData = "removeData";
    private final static String M_setNotificationEnable = "setNotificationEnable";
    private final static String M_exitApp = "exitApp";
    private final static String M_getAppInfo = "getAppInfo";
    private final static String M_preferredLanguages = "preferredLanguages";
    private final static String M_currentLocale = "currentLocale";
    private final static String M_setLanguagePerApp = "setLanguagePerApp";
    private final static String M_isLanguagePerAppSettingSupported = "isLanguagePerAppSettingSupported";
    public final static String M_getNativeValue = "getNativeValue";
    public final static String M_getNativeProp = "getNativeProp";

    /**
     * BaseCallback
     *
     * @param methodChannel methodChannel
     * @param eventHandler eventHandler
     */
    public CommonMessage(MethodChannel methodChannel, UTEPedEventHandler eventHandler) {
        super(methodChannel, eventHandler);
    }

    @Override
    public boolean methodCallConsumed(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
        if (!call.hasArgument(Const.KEY_METHOD))
            return false;

        if (super.methodCallConsumed(call, result))
            return true;

        UteBleConnection uteBleConnection = uteBleClient.getUteBleConnection();
        boolean consumed = true;
        boolean enable;
        boolean success = false;
        Response<?> rsp;
        String method = call.argument(Const.KEY_METHOD);
        assert method != null;
        switch (method) {
            case M_setLogEnable:
                enable = Boolean.TRUE.equals(call.argument("enable"));
                LogUtils.setLogEnable(enable);
                Logger.setEnable(enable);
                result.success(true);
                break;

            case M_checkNotificationEnable:
                if (Tools.isNotificationListenerEnabled(Tools.getApplicationContext())) {
                    Tools.checkNotificationService();
                    MusicRemind.shareInstance().init();
                }
                else {
                    Tools.openNotificationListenSettings(Tools.getApplicationContext());
                }
                result.success(true);
                break;

            case M_isNotificationEnable:
                result.success(Tools.isNotificationListenerEnabled(Tools.getApplicationContext()));
                break;

            case M_toNotificationPage:
                Tools.openNotificationListenSettings(Tools.getApplicationContext());
                break;

            case M_syncData:
                String action = call.argument(Const.KEY_ACTION);
                DataSyncHelper.getInstance().fetchDataAsync(action);
                if (uteBleClient.isConnected()) {
                    rsp = uteBleConnection.setTimeClock(getTimeClock());
                    success = rsp.isSuccess();
                }
                result.success(success);
                break;

            case Const.M_setSyncDataEnable:
                enable = Boolean.TRUE.equals(call.argument(Const.KEY_ENABLE));
                SPHelper.shareInstance().putAndCommit(Const.M_setSyncDataEnable, enable);
                result.success(true);
                break;

            case Const.M_setLogFileEnable:
                enable = Boolean.TRUE.equals(call.argument(Const.KEY_ENABLE));
                SPHelper.shareInstance().putAndCommit(Const.M_setLogFileEnable, enable);
                result.success(true);
                break;

            case M_removeData:
                if (call.hasArgument(Const.KEY_ADDRESS)) {
                    String address = call.argument(Const.KEY_ADDRESS);
                    DeviceHelper.getInstance().onDeviceDisconnect(address);
                    success = true;
                }
                result.success(success);
                break;

            case M_setNotificationEnable:
                enable = Boolean.TRUE.equals(call.argument(Const.KEY_ENABLE));
                if (call.hasArgument(Const.KEY_PACKAGE)) {
                    String packageName = call.argument(Const.KEY_PACKAGE);
                    DeviceHelper.getInstance().save(packageName, enable);
                }
                result.success(true);
                break;

            case M_exitApp:
                Tools.exitApp();
                result.success(true);
                break;

            case Const.M_checkBT3:
                if (uteBleClient.isConnected()) {
                    BluetoothHelper.getInstance().bindBT3(uteBleClient.getBluetoothDevice());
                }
                result.success(true);
                break;

            case M_getAppInfo:
                result.success(Tools.getAppInfo());
                break;

            case Const.M_setDeviceFilter:
                enable = Boolean.TRUE.equals(call.argument(Const.KEY_ENABLE));
                SPHelper.shareInstance().putAndCommit(Const.M_setDeviceFilter, enable);
                result.success(true);
                break;

            case Const.M_useDatabaseByName:
                String name = call.argument(Const.KEY_NAME);
                SPHelper.shareInstance().putAndCommit(Const.M_useDatabaseByName, name);
                result.success(true);
                break;

            case M_preferredLanguages:
                result.success(getPreferredLanguages());
                break;

            case M_currentLocale:
                result.success(getCurrentLocale());
                break;

            case M_setLanguagePerApp:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    result.success(setLanguagePerAppSetting(call));
                } else {
                    result.success(false);
                }
                break;

            case M_isLanguagePerAppSettingSupported:
                result.success(isLanguagePerAppSettingSupported());
                break;

            case Const.M_setLanguage:
                if (call.hasArgument(Const.KEY_LANGUAGE) && uteBleClient.isConnected()) {
                    int language = call.argument(Const.KEY_LANGUAGE);
                    if (call.hasArgument(Const.KEY_UNITS)) {
                        int units = call.argument(Const.KEY_UNITS);
                        rsp = uteBleConnection.setLanguage(language, units);
                    }
                    else {
                        rsp = uteBleConnection.setLanguage(language);
                    }

                    success = rsp.getErrorCode() == Const.CODE_SUCCESS;
                }

                result.success(success);
                break;

            case Const.M_queryDeviceSupportLanguage:
                if (uteBleClient.isConnected()) {
                    Response<List<Integer>> lanRsp = uteBleConnection.queryDeviceSupportLanguage();
                    result.success(lanRsp.getData());
                }
                else {
                    result.success(new ArrayList<Integer>());
                }

                break;

            case M_getNativeValue:
                name = call.argument(Const.KEY_NAME);
                String type = call.argument(Const.KEY_TYPE);
                if ("String".equals(type)) {
                    result.success(SPHelper.shareInstance().getString(name));
                }
                else if ("bool".equals(type)) {
                    result.success(SPHelper.shareInstance().getBoolean(name, false));
                }
                else if ("int".equals(type)) {
                    result.success(SPHelper.shareInstance().getInt(name, -1));
                }
                else if ("long".equals(type)) {
                    result.success(SPHelper.shareInstance().getLong(name, -1L));
                }

                break;

            case M_getNativeProp:
                name = call.argument(Const.KEY_NAME);
                if ("is24HourFormat".equals(name)) {
                    result.success(DateFormat.is24HourFormat(Tools.getApplicationContext()));
                }
                else {
                    result.success(false);
                }
                break;

            default:
                consumed = false;
        }

        return consumed;
    }

    @Override
    public String getPath() {
        return PATH;
    }

    private String getCurrentLocale() {
        return getLocaleTag(Locale.getDefault());
    }


    private List<String> getPreferredLanguages() {
        List<String> result = new ArrayList<>();

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            LocaleListCompat list = LocaleListCompat.getAdjustedDefault();
            for (int i = 0; i < list.size(); i++) {
                result.add(getLocaleTag(list.get(i)));
            }
        } else {
            result.add(getCurrentLocale());
        }

        return result;
    }

    private String getLocaleTag(Locale locale) {
        return locale.toLanguageTag();
    }

    @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
    private boolean isLanguagePerAppSettingSupported() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
    }

    @RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
    @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
    private boolean setLanguagePerAppSetting(MethodCall methodCall) {
        final String locale = methodCall.argument("locale");
        final Handler mainHandler = new Handler(Tools.getApplicationContext().getMainLooper());
        final Runnable myRunnable = () -> {
            final LocaleList appLocale = LocaleList.forLanguageTags(locale);
            final LocaleManager service = Tools.getApplicationContext().getSystemService(LocaleManager.class);
            service.setApplicationLocales(appLocale);
        };
        mainHandler.post(myRunnable);
        return true;
    }
}
